]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
ShellUserVerifier: catch DBus errors and report them to the user
authorGiovanni Campagna <gcampagna@src.gnome.org>
Thu, 6 Sep 2012 14:40:13 +0000 (16:40 +0200)
committerFlorian Müllner <fmuellner@gnome.org>
Wed, 19 Sep 2012 09:50:57 +0000 (11:50 +0200)
Instead of leaving the login or unlock dialogs in an inconsistent state,
catch DBus errors and show an Authentication Error message. The error
details are logged in the session logs.

https://bugzilla.gnome.org/show_bug.cgi?id=683060

js/gdm/loginDialog.js
js/gdm/util.js
js/ui/unlockDialog.js

index 3d7996c4f72e44a0e72c3f6ce0afd8a6d0e18438..8cb43958151b4eca17c39d4a923c4fbcc0fef4c4 100644 (file)
@@ -649,6 +649,10 @@ const LoginDialog = new Lang.Class({
         this._userVerifier.connect('ask-question', Lang.bind(this, this._askQuestion));
         this._userVerifier.connect('show-message', Lang.bind(this, this._showMessage));
         this._userVerifier.connect('reset', Lang.bind(this, this._onReset));
+        this._userVerifier.connect('not-supported', Lang.bind(this, function(verifier, error) {
+            Main.notifyError(_("Configuration problem: Could not connect to GDM"), error.message);
+            this._onReset();
+        }));
 
         this._userVerifier.connect('show-login-hint', Lang.bind(this, this._showLoginHint));
         this._userVerifier.connect('hide-login-hint', Lang.bind(this, this._hideLoginHint));
index 681c0a69bd028ca6e39d1700062b0152b11087cb..4d4754d6db237a5ac0cc2700b0e462ccf7d4d0a4 100644 (file)
@@ -141,34 +141,43 @@ const ShellUserVerifier = new Lang.Class({
             }));
     },
 
+    _reportInitError: function(where, error) {
+        logError(error, where);
+        this._hold.relase();
+
+        this.emit('show-message', _("Authentication error"), 'login-dialog-message-warning');
+        this._verificationFailed(false);
+    },
+
     _reauthenticationChannelOpened: function(client, result) {
         try {
             this._userVerifier = client.open_reauthentication_channel_finish(result);
-            this._connectSignals();
-            this._beginVerification();
-
-            this._hold.release();
-        } catch (e) {
-            if (this._reauthOnly) {
-                if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
-                    return;
-
-                logError(e, 'Failed to open reauthentication channel');
-                this.emit('verification-failed');
-                this._hold.release();
-                return;
-            }
-
-            // If there's no session running, or it otherwise fails, then fall back
-            // to performing verification from this login session
+        } catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
+            return;
+        } catch(e if e.matches(Gio.DBusError, Gio.DBusError.ACCESS_DENIED) &&
+                !this._reauthOnly) {
+            // Gdm emits org.freedesktop.DBus.Error.AccessDenied when there is
+            // no session to reauthenticate. Fall back to performing verification
+            // from this login session
             client.get_user_verifier(this._cancellable, Lang.bind(this, this._userVerifierGot));
+            return;
+        } catch(e) {
+            this._reportInitError('Failed to open reauthentication channel', e);
+            return;
         }
+
+        this._connectSignals();
+        this._beginVerification();
+        this._hold.release();
     },
 
     _userVerifierGot: function(client, result) {
         try {
             this._userVerifier = client.get_user_verifier_finish(result);
-        } catch(e if e.matches(Gio.IOErrorEnum, Gio.ErrorEnum.CANCELLED)) {
+        } catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
+            return;
+        } catch(e) {
+            this._reportInitError('Failed to obtain user verifier', e);
             return;
         }
 
@@ -199,6 +208,9 @@ const ShellUserVerifier = new Lang.Class({
                     obj.call_begin_verification_for_user_finish(result);
                 } catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
                     return;
+                } catch(e) {
+                    this._reportInitError('Failed to start verification for user', e);
+                    return;
                 }
 
                 this._hold.release();
@@ -215,6 +227,9 @@ const ShellUserVerifier = new Lang.Class({
                         obj.call_begin_verification_for_user_finish(result);
                     } catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
                         return;
+                    } catch(e) {
+                        this._reportInitError('Failed to start fingerprint verification for user', e);
+                        return;
                     }
 
                     this._hold.release();
@@ -228,6 +243,9 @@ const ShellUserVerifier = new Lang.Class({
                     obj.call_begin_verification_finish(result);
                 } catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
                     return;
+                } catch(e) {
+                    this._reportInitError('Failed to start verification', e);
+                    return;
                 }
 
                 this._hold.release();
@@ -306,23 +324,27 @@ const ShellUserVerifier = new Lang.Class({
         this.emit('verification-complete');
     },
 
-    _verificationFailed: function() {
+    _verificationFailed: function(retry) {
         // For Not Listed / enterprise logins, immediately reset
         // the dialog
         // Otherwise, we allow ALLOWED_FAILURES attempts. After that, we
         // go back to the welcome screen.
 
-        if (!this._userName ||
-            (++this._failCounter) == this._settings.get_int(ALLOWED_FAILURES_KEY)) {
+        let canRetry = retry && this._userName &&
+            this._failCounter < this._settings.get_int(ALLOWED_FAILURES_KEY);
+
+        if (canRetry) {
+            this._failCounter++;
+
+            this.clear();
+            this.begin(this._userName, new Batch.Hold());
+        } else {
             // Allow some time to see the message, then reset everything
             Mainloop.timeout_add(3000, Lang.bind(this, function() {
                 this.cancel();
 
                 this._onReset();
             }));
-        } else {
-            this.clear();
-            this.begin(this._userName, new Batch.Hold());
         }
 
         this.emit('verification-failed');
@@ -333,7 +355,7 @@ const ShellUserVerifier = new Lang.Class({
         // But if, e.g., fingerprint fails, still give
         // password authentication a chance to succeed
         if (serviceName == PASSWORD_SERVICE_NAME) {
-            this._verificationFailed();
+            this._verificationFailed(true);
         }
 
         this.emit('hide-login-hint');
index 127a924c76c888d95153d4c9bc0e0810d5547034..8701a430d2d2ac119febc516fb6b51b379a136de 100644 (file)
@@ -133,6 +133,12 @@ const UnlockDialog = new Lang.Class({
         this._userVerifier.connect('show-login-hint', Lang.bind(this, this._showLoginHint));
         this._userVerifier.connect('hide-login-hint', Lang.bind(this, this._hideLoginHint));
 
+        this._userVerifier.connect('not-supported', Lang.bind(this, function(verifier, error) {
+            Main.notifyError(_("Could not connect to GDM. Screen locking was automatically disabled."), error.message);
+            this._userVerifier.clear();
+            this.emit('unlocked');
+        }));
+
         this._userWidget = new UserWidget(this._user);
         this.contentLayout.add_actor(this._userWidget.actor);